import misaka as m
from pathlib import Path
from typing import List, Tuple, Union

import jinja2 as jj
import pandas as pd
from pyvision.core import markdown2
from pyvision.core.DataModel import Layout, RowContainer
from pyvision.core.Jsonable import tojson
from pyvision.helpler.IDs import get_gid
from pyvision.wrappers.Components import (AltChart, Component, DataSetComponent,
                                          MplChart, RawHtml)
from pyvision.wrappers.DataSet import DataSet, DataSetMapping

_m_this_dir_path = Path(__file__).parent


class Report():
    pass

    def __init__(self) -> None:
        self.layout = Layout()
        self.datasets = DataSetMapping()

    def add_md(self, content: str):
        self.add_html(m.html(content))
        return self

    def add_mpl_chart(self, fig):
        cp = MplChart(get_gid(), fig)
        self.add_row(cp)
        return self

    def add_alt_chart(self, chart, dataset: DataSet):
        spec = chart.to_dict()
        del spec['data']
        del spec['datasets']
        cp = AltChart(get_gid(), dataset, spec)
        self.add_row(cp)
        return self

    def add_html(self, content: str):
        rh = RawHtml(get_gid(), content)
        self.add_row(rh)

        return self

    def add_table(self, data: Union[DataSet, pd.DataFrame]):
        # make sure data is DataSet
        if isinstance(data, pd.DataFrame):
            data = DataSet(data)

        # make sure dataset in self.datasets
        if not data.id in self.datasets:
            self.datasets[data.id] = data

        ds: DataSet = self.datasets[data.id]
        self.add_row(ds.new_table(get_gid()))
        return self

    def add_row(self, *cps: Component):

        for cp in (c for c in cps if isinstance(c, DataSetComponent)):
            if not cp.dataSet.id in self.datasets:
                self.datasets[cp.dataSet.id] = cp.dataSet

        cpModels = [cp._get_component_model() for cp in cps]
        row = RowContainer().add_components(*cpModels)
        self.layout.add_row(row)

        return self

    def to_html(self, file):
        file = Path(file)
        env = jj.Environment(
            loader=jj.FileSystemLoader(_m_this_dir_path.parent))
        tl = env.get_template('template/index.html')
        cts = ''
        with open(_m_this_dir_path.parent / 'template/template_js', mode='r', encoding='utf8') as f:
            dataset = tojson(self.datasets.to_json_dict())
            cps = tojson(self.layout)
            cts = f.read().replace('@dataset@', dataset).replace('@cps@', cps)

        with open(file, mode='w', encoding='utf8') as f:
            res = tl.render(js=cts)
            f.write(res)

        print(f'成功生成结果：{file.absolute()}')
